package com.zzhardy.log;

import java.util.Date;

import javax.servlet.http.HttpServletRequest;

import com.zzhardy.annotation.log.LogAccess;
import com.zzhardy.dao.SysOperateLogDao;
import com.zzhardy.model.SysOperateLog;
import org.apache.commons.lang3.StringUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

/**
 * @author 阡陌之中
 * @Description: AOP + 注解形式追加项目日志系统
 * @date 2021/01/14
 */
@Component
@Aspect
public class LogAspect {
    
    @Autowired
    private SysOperateLogDao sysOperateLogDao;
    
    @Pointcut(value = "@annotation(com.zzhardy.annotation.log.LogAccess)")
    public void access() {
    
    }
    
    @Before("access()")
    public void deBefore(JoinPoint joinPoint) throws Throwable {
    }
    
    /**
     * 对使用注解注释了的action进行保存操作记录
     */
    @Around("@annotation(logAccess)")
    public Object around(ProceedingJoinPoint pjp, LogAccess logAccess) {
        //获取注解里的值
        SysOperateLog sysOperateLog = new SysOperateLog();
        //读取中的用户
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String url = String.format("URL : %s%s Request Method : %s",
                                   request.getRequestURL().toString(),
                                   StringUtils.isNotBlank(request.getQueryString()) ? "?" + request.getQueryString() : "",
                                   request.getMethod());
        sysOperateLog.setUrl(url);
        sysOperateLog.setSysId(100);
        sysOperateLog.setUnitId(100);
        sysOperateLog.setCreateId(100);
        sysOperateLog.setMethod(pjp.getSignature().getDeclaringTypeName() + "." + pjp.getSignature().getName());
        sysOperateLog.setArgs(request.getQueryString());
        sysOperateLog.setIp(request.getRemoteAddr());
        sysOperateLog.setFunction(logAccess.desc());
        sysOperateLog.setType(logAccess.type().GetDescription());
        sysOperateLog.setCreateTime(new Date());
        sysOperateLogDao.insert(sysOperateLog);
        try {
            return pjp.proceed();
        } catch (Throwable throwable) {
            throwable.printStackTrace();
            return null;
        }
    }
    
    /**
     * 出现异常是进行保存异常信息与操作记录
     */
    @AfterThrowing(value = "@annotation(logAccess)", throwing = "e")
    private void doAfterThrow(JoinPoint joinPoint, LogAccess logAccess, Throwable e) {
        SysOperateLog sysOperateLog = new SysOperateLog();
        //读取中的用户
        HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        String url = String.format("URL : %s%s Request Method : %s",
                                   request.getRequestURL().toString(),
                                   StringUtils.isNotBlank(request.getQueryString()) ? "?" + request.getQueryString() : "",
                                   request.getMethod());
        sysOperateLog.setUrl(url);
        sysOperateLog.setMethod(joinPoint.getSignature().getDeclaringTypeName() + "." + joinPoint.getSignature().getName());
        sysOperateLog.setArgs(request.getQueryString());
        sysOperateLog.setIp(request.getRemoteAddr());
        //获取类名
        String className = joinPoint.getTarget().getClass().getSimpleName();
        //获取方法名
        String methodName = joinPoint.getSignature().getName();
        String location   = className + "." + methodName + " : ";
        sysOperateLog.setErrorMsg(location + e.getClass().getSimpleName() + " : " + e.getMessage());
        sysOperateLog.setType(logAccess.type().GetDescription());
        sysOperateLog.setFunction(logAccess.desc());
        sysOperateLog.setSysId(100);
        sysOperateLog.setUnitId(100);
        sysOperateLog.setCreateId(100);
        sysOperateLog.setCreateTime(new Date());
        sysOperateLogDao.insert(sysOperateLog);
    }
}
